Micron Document
`:top
`!`F33f`_`[Generische Programmierung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Generische_Programmierung]`_`f in `F33f`_`[Java`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Java_(Programmiersprache)]`_`f`! wird durch sog. `*Generics`* seit Java 1.5 ermöglicht. Der Begriff steht synonym für „parametrisierte Typen“. Die Idee dahinter ist, zusätzliche `F33f`_`[Variablen`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Variable_(Programmierung)]`_`f für `F33f`_`[Datentypen`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Datentyp]`_`f einzuführen. Diese `*Typ-Variablen`* repräsentieren zum Zeitpunkt der Implementierung unbekannte Typen. Erst bei der Verwendung der `F33f`_`[Klassen`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Klasse_(objektorientierte_Programmierung)]`_`f, `F33f`_`[Schnittstellen`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Schnittstelle_(Objektorientierung)]`_`f und `F33f`_`[Methoden`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Methode_(Programmierung)]`_`f werden diese Typ-Variablen durch konkrete Typen ersetzt. Damit kann `F33f`_`[typsichere`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Typsicherheit]`_`f Programmierung meistens gewährleistet werden. Jedoch nicht immer.`:cite-ref-1[`F5bf`_`[1`#cite-note-1]`_`f]

>>Contents

• `F0af`_`[Das Konzept`#das-konzept]`_`f
• `F0af`_`[Praktische Beispiele`#praktische-beispiele]`_`f
• `F0af`_`[Varianzfälle`#varianzf-lle]`_`f
• `F0af`_`[Invarianz`#invarianz]`_`f
• `F0af`_`[Kovarianz`#kovarianz]`_`f
• `F0af`_`[Kontravarianz`#kontravarianz]`_`f
• `F0af`_`[Uneingeschränkte parametrische Polymorphie`#uneingeschr-nkte-parametrische-polymorphie]`_`f
• `F0af`_`[Weblinks`#weblinks]`_`f
• `F0af`_`[Einzelnachweise`#einzelnachweise]`_`f

-─

>>Das Konzept

Ab Version 5.0 („Tiger“, 2004 veröffentlicht) steht auch in der Programmiersprache Java mit den Generics ein `F33f`_`[syntaktisches`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Syntax]`_`f Mittel für die generische Programmierung zur Verfügung. Damit lassen sich Klassen und Methoden (Methoden auch unabhängig von ihren Klassen) mit `*Typen`* parametrisieren. Damit werden der Sprache einige ähnliche Möglichkeiten eröffnet, die sich vergleichbar bei den `F33f`_`[Templates`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Template_(Programmierung)]`_`f in `F33f`_`[C++`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=C++]`_`f bieten.

Prinzipiell gibt es aber durchaus wesentliche Unterschiede. Während in Java über die `*Schnittstelle`* der Typparameter parametrisiert wird, wird in C++ direkt über den `*Typ`* des Typparameters selbst parametrisiert. Der `F33f`_`[Quelltext`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Quelltext]`_`f eines C++-Templates muss für den Anwender (d. h. beim Einsetzen des Typparameters) verfügbar sein, während ein `F33f`_`[generischer Java-Typ`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Generischer_Typ]`_`f auch als übersetzter `F33f`_`[Bytecode`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Bytecode]`_`f veröffentlicht werden kann. Für verschiedene konkret verwendete Typparameter produziert der `F33f`_`[Compiler`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Compiler]`_`f duplizierten Zielcode.

Beispielsweise bietet die Funktion `B100`F9d9std::sort`f`b in C++ die Möglichkeit, alle `F33f`_`[Container`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Container_(Informatik)]`_`f zu sortieren, die bestimmte Methoden anbieten (hier speziell `B100`F9d9begin()`f`b und `B100`F9d9end()`f`b, die jeweils einen `F33f`_`[Iterator`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Iterator]`_`f liefern) und deren Typparameter den `B100`F9d9operator<`f`b implementiert (oder explizit eine andere Vergleichsfunktion angegeben wurde). Ein Nachteil, der sich durch dieses System ergibt, ist die (für den Programmierer!) schwierigere Übersetzung. Der Compiler hat keine andere Möglichkeit, als den Typparameter in jedem Fall durch den geforderten konkreten Typ zu ersetzen und den ganzen Code erneut zu kompilieren.

Sehr leicht können bei unpassenden Typparametern und anderen Problemen komplizierte und unverständliche Compiler-Meldungen entstehen, was einfach mit der Tatsache zusammenhängt, dass die konkreten Anforderungen an die Typparameter unbekannt sind. Die Arbeit mit C++-Templates erfordert deshalb eine lückenlose Dokumentation der Anforderungen an einen Typparameter. Durch Template-`F33f`_`[Metaprogrammierung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Metaprogrammierung]`_`f können die meisten Anforderungen (`F33f`_`[Basisklasse`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Basisklasse]`_`f, Vorhandensein von Methoden, Kopierbarkeit, Zuweisbarkeit etc.) auch in speziellen Konstrukten abgefragt werden, wodurch sich lesbarere Fehlermeldungen ergeben. Obgleich sie standardkonform sind, werden diese Konstrukte jedoch nicht von allen Compilern unterstützt.

Dagegen sind den generischen Klassen und Methoden in Java die Anforderungen (`F33f`_`[englisch`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Englische_Sprache]`_`f constraints) an ihre eigenen Typparameter bekannt. Um eine Collection (ohne Comparator) zu sortieren, müssen die enthaltenen Elemente vom Typ Comparable sein, also dieses Interface implementiert haben. Der Compiler muss lediglich prüfen, ob der Typparameter ein Untertyp von Comparable ist, und kann damit schon sicherstellen, dass der Code korrekt ist (d. h. die erforderliche Methode compareTo verfügbar ist). Weiterhin wird ein und derselbe Code für alle konkreten Typen verwendet und nicht jedes Mal dupliziert.

>>Praktische Beispiele

Ein Programm verwendet eine `B100`F9d9ArrayList`f`b, um eine `F33f`_`[Liste`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Liste_(Datenstruktur)]`_`f von `B100`F9d9JButton`f`bs zu speichern.

Bisher war die `B100`F9d9ArrayList`f`b auf den Typ `B100`F9d9Object`f`b fixiert:

`B100`F9d9List list = new ArrayList();`f`b
`B100`F9d9list.add(new JButton("Button 1"));`f`b
`B100`F9d9list.add(new JButton("Button 2"));`f`b
`B100`F9d9list.add(new JButton("Button 3"));`f`b
`B100`F9d9list.add(new JButton("Button 4"));`f`b
`B100`F9d9list.add(new JButton("Button 5"));`f`b
`B100`F9d9`f`b
`B100`F9d9for (int i = 0; i < list.size(); i++) {`f`b
`B100`F9d9 JButton button = (JButton) list.get(i);`f`b
`B100`F9d9 button.setBackground(Color.white);`f`b
`B100`F9d9}`f`b

Man beachte die notwendige `F33f`_`[explizite Typumwandlung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Typumwandlung]`_`f (auch „Cast“ genannt) sowie die Typunsicherheit, die damit verbunden ist. Man könnte versehentlich ein `F33f`_`[Objekt`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Objekt_(Programmierung)]`_`f in der `B100`F9d9ArrayList`f`b speichern, das keine Instanz der Klasse `B100`F9d9JButton`f`b ist. Die Information über den genauen Typ geht beim Einfügen in die Liste verloren, der Compiler kann also nicht verhindern, dass zur `F33f`_`[Laufzeit`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Laufzeit_(Informatik)]`_`f bei der expliziten Typumwandlung von `B100`F9d9JButton`f`b eine `B100`F9d9ClassCastException`f`b auftritt.

Mit `*generischen Typen`* ist in Java Folgendes möglich:

`B100`F9d9List<JButton> list = new ArrayList<JButton>();`f`b
`B100`F9d9list.add(new JButton("Button 1"));`f`b
`B100`F9d9list.add(new JButton("Button 2"));`f`b
`B100`F9d9list.add(new JButton("Button 3"));`f`b
`B100`F9d9list.add(new JButton("Button 4"));`f`b
`B100`F9d9list.add(new JButton("Button 5"));`f`b
`B100`F9d9`f`b
`B100`F9d9for (int i = 0; i < list.size(); i++)`f`b
`B100`F9d9 list.get(i).setBackground(Color.white);`f`b

Beim Auslesen ist nun keine explizite Typumwandlung mehr notwendig, beim Speichern ist es nur noch möglich, JButtons in der `B100`F9d9ArrayList`f`b `*list`* abzulegen.

Ab Java7 ist die Instanzierung generischer Typen vereinfacht worden. Die erste Zeile in obigem Beispiel kann seit Java 7 folgendermaßen geschrieben werden:

`B100`F9d9List<JButton> list = new ArrayList<>();`f`b

Die beiden leeren spitzen Klammern werden aufgrund ihrer Form auch als `*Diamant-Operator`* (`F33f`_`[englisch`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Englische_Sprache]`_`f Diamond-Operator) bezeichnet.`:cite-ref-2[`F5bf`_`[2`#cite-note-2]`_`f]`:cite-ref-3[`F5bf`_`[3`#cite-note-3]`_`f]

Durch Kombination von generischen Typen mit den erweiterten For-Schleifen lässt sich obiges Beispiel kürzer fassen:

`B100`F9d9List<JButton> list = new ArrayList<>();`f`b
`B100`F9d9list.add(new JButton("Button 1"));`f`b
`B100`F9d9list.add(new JButton("Button 2"));`f`b
`B100`F9d9list.add(new JButton("Button 3"));`f`b
`B100`F9d9list.add(new JButton("Button 4"));`f`b
`B100`F9d9list.add(new JButton("Button 5"));`f`b
`B100`F9d9`f`b
`B100`F9d9for (JButton b: list)`f`b
`B100`F9d9 b.setBackground(Color.white);`f`b

Ein Beispiel für eine generische Klasse, die zwei Objekte von beliebigem, aber einander gleichem Typ beinhaltet, liefert der folgende Beispielcode:

`B100`F9d9public class DoubleObject<T> {`f`b
`B100`F9d9 private T object1;`f`b
`B100`F9d9 private T object2;`f`b
`B100`F9d9`f`b
`B100`F9d9 public DoubleObject(T object1, T object2) {`f`b
`B100`F9d9 this.object1 = object1;`f`b
`B100`F9d9 this.object2 = object2;`f`b
`B100`F9d9 }`f`b
`B100`F9d9`f`b
`B100`F9d9 public String toString() {`f`b
`B100`F9d9 return this.object1 + ", " + this.object2;`f`b
`B100`F9d9 }`f`b
`B100`F9d9`f`b
`B100`F9d9 public static void main(String[] args) {`f`b
`B100`F9d9 DoubleObject<String> s = new DoubleObject<>("abc", "def");`f`b
`B100`F9d9 DoubleObject<Integer> i = new DoubleObject<>(123, 456);`f`b
`B100`F9d9 System.out.println("DoubleObject<String> s=" + s.toString());`f`b
`B100`F9d9 System.out.println("DoubleObject<Integer> i=" + i.toString());`f`b
`B100`F9d9 }`f`b
`B100`F9d9}`f`b

>>Varianzfälle

In Java können die nachfolgenden Varianzfälle unterschieden werden. Sie bieten jeweils eine völlig eigenständige Flexibilität beim Umgang mit generischen Typen und sind jeweils absolut statisch typsicher.

>>>Invarianz

Bei Invarianz ist der Typparameter eindeutig. Damit bietet Invarianz die größtmögliche Freiheit bei der Benutzung des Typparameters. Beispielsweise sind für die Elemente einer `B100`F9d9ArrayList<Integer>`f`b alle Aktionen erlaubt, die auch bei der direkten Benutzung eines einzelnen Integers erlaubt sind (inklusive `F33f`_`[Autoboxing`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Autoboxing]`_`f). Beispiel:

`B100`F9d9List<Integer> list = new ArrayList<Integer>();`f`b
`B100`F9d9// ...`f`b
`B100`F9d9Integer x = list.get(index);`f`b
`B100`F9d9list.get(index).methodeVonInteger();`f`b
`B100`F9d9list.set(index, 98347); // Autoboxing, entspricht Integer.valueOf(98347)`f`b
`B100`F9d9int y = list.get(index); // Auto-Unboxing`f`b

Diese Möglichkeiten werden mit wenig Flexibilität bei der `F33f`_`[Zuweisung`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Zuweisung]`_`f von Objekten der generischen Klasse selbst erkauft. Beispielsweise ist Folgendes nicht erlaubt:

`B100`F9d9List<Number> list = new ArrayList<Integer>();`f`b

und das, obwohl Integer von Number abgeleitet ist. Der Grund liegt darin, dass der Compiler hier nicht mehr sicherstellen kann, dass keine Typfehler auftreten. Mit `F33f`_`[Arrays`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Array_(Datentyp)]`_`f, die eine solche Zuweisung erlauben, hat man schlechte Erfahrungen gemacht:

`B100`F9d9// OK, Integer[] ist abgeleitet von Number[]`f`b
`B100`F9d9Number[] array = new Integer[10];`f`b
`B100`F9d9`f`b
`B100`F9d9// ArrayStoreException zur Laufzeit: Double -> Integer sind nicht`f`b
`B100`F9d9// zuweisungskompatibel`f`b
`B100`F9d9array[0] = new Double(5.0);`f`b

>>>Kovarianz

Man bezeichnet Arrays als `F33f`_`[kovariant`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Kovarianz_und_Kontravarianz]`_`f, was besagt:

Aus

T extends V

folgt:

T[] extends V[]

oder allgemeiner:

Aus

T extends V

folgt:

GenerischerTyp<T> extends GenerischerTyp<V>

Es verhält sich also der Array-Typ bzgl. der `F33f`_`[Vererbungshierarchie`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Vererbung_(Programmierung)]`_`f genauso wie der Typparameter. Kovarianz ist auch mit generischen Typen möglich, allerdings nur mit Einschränkungen, so dass Typfehler zur `F33f`_`[Kompilierzeit`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Übersetzungszeit]`_`f ausgeschlossen werden können.

Referenzen müssen mit der Syntax `!? extends T`! explizit als kovariant gekennzeichnet werden. T heißt `*upper typebound`*, also der allgemeinste Typparameter, der erlaubt ist.

`B100`F9d9List<? extends Number> list;`f`b
`B100`F9d9list = new ArrayList<Double>();`f`b
`B100`F9d9list = new ArrayList<Long>();`f`b
`B100`F9d9list = new ArrayList<Integer>();`f`b
`B100`F9d9`f`b
`B100`F9d9// Typfehler vom Compiler`f`b
`B100`F9d9list.set(index, myInteger);`f`b
`B100`F9d9`f`b
`B100`F9d9// OK aber Warnung vom Compiler: unchecked cast`f`b
`B100`F9d9((List<Integer>) list).set(index, myInteger);`f`b

Das Ablegen von Elementen in diesen Listen ist nicht möglich, da dies, wie oben beschrieben, nicht typsicher ist (Ausnahme: `B100`F9d9`F33f`_`[null`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Nullwert]`_`f`f`b kann abgelegt werden). Bereits zur Kompilierzeit tritt ein Fehler auf. Allgemeiner gesagt, ist die Zuweisung

?


? extends T

nicht erlaubt.

Möglich dagegen ist das Auslesen von Elementen:

`B100`F9d9Number n = list.get(index); // OK`f`b
`B100`F9d9Integer i = list.get(index); // Typfehler: Es muss sich bei '? extends Number'`f`b
`B100`F9d9 // nicht um ein Integer handeln.`f`b
`B100`F9d9Integer j = (Integer) list.get(index); // OK`f`b

Die Zuweisung

? extends T


T (oder Basisklasse)

ist also erlaubt, nicht aber die Zuweisung

? extends T


abgeleitet von T

Generics bieten also wie Arrays kovariantes Verhalten, verbieten aber alle Operationen, die typunsicher sind.

>>>Kontravarianz

Kontravarianz bezeichnet das Verhalten der Vererbungshierarchie des generischen Typs entgegen der Hierarchie seines Typparameters. Übertragen auf das obige Beispiel würde das bedeuten: Eine Liste<Number> wäre zuweisungskompatibel zu einer Liste<Double>. Dies wird folgendermaßen bewerkstelligt:

`B100`F9d9List<? super Double> list;`f`b
`B100`F9d9list = new ArrayList<Number>();`f`b
`B100`F9d9list = new ArrayList<Double>();`f`b
`B100`F9d9list = new ArrayList<Object>();`f`b

Ein Objekt, das sich kontravariant verhält, darf keine Annahmen darüber machen, inwiefern ein Element vom Typ V von T abgeleitet ist, wobei T der `*lower Typebound`* ist (im Beispiel von `B100`F9d9? super Double`f`b ist T `B100`F9d9Double`f`b). Deshalb kann aus den obigen Listen nicht gelesen werden:

`B100`F9d9// Fehler: 'list' könnte vom Typ List<Object> sein`f`b
`B100`F9d9Number x = list.get(index);`f`b
`B100`F9d9`f`b
`B100`F9d9// Fehler: 'list' könnte List<Object> oder List<Number> sein`f`b
`B100`F9d9Double x = list.get(index);`f`b
`B100`F9d9`f`b
`B100`F9d9// Die einzige Ausnahme: Objects sind auf jeden Fall in der Liste`f`b
`B100`F9d9Object x = list.get(index);`f`b

Nicht erlaubt, da nicht typsicher, ist also die Zuweisung `!? super T → (abgeleitet von Object)`!

Unschwer zu erraten: Im Gegenzug kann in eine solche Liste ein Element abgelegt werden:

`B100`F9d9List<? super Number> list;`f`b
`B100`F9d9list.add(new Double(3.0)); // OK: 'list' hat immer den Typ List<Number>`f`b
`B100`F9d9 // oder List<Basisklasse von Number>. Damit`f`b
`B100`F9d9 // ist die Zuweisung Double -> T immer erlaubt.`f`b

>>>Uneingeschränkte parametrische Polymorphie

Zu guter Letzt bieten Generics noch gänzlich polymorphes Verhalten an. Hierbei kann keinerlei Aussage über die Typparameter gemacht werden, denn es wird in beide Richtungen keine Grenze angegeben. Dafür wurde die `F33f`_`[Wildcard`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Wildcard_(Java)]`_`f definiert. Sie wird durch ein Fragezeichen repräsentiert.

`B100`F9d9List<?> list;`f`b
`B100`F9d9list = new ArrayList<Integer>();`f`b
`B100`F9d9list = new ArrayList<Object>();`f`b
`B100`F9d9list = new ArrayList<String>();`f`b
`B100`F9d9// ...`f`b

Der Typparameter selbst kann hierbei nicht genutzt werden, da keine Aussage möglich ist. Lediglich die Zuweisung T → Object ist erlaubt, da T auf jeden Fall ein Object ist. Im Gegenzug ist garantiert, dass der Code mit `*allen`* Ts arbeiten kann.

Nützlich kann so etwas sein, wenn man nur mit dem generischen Typ arbeitet:

`B100`F9d9// Keine Informationen über den Typparameter nötig, kann ''beliebige'' Listen`f`b
`B100`F9d9// aufnehmen.`f`b
`B100`F9d9int readSize(List<?> list) {`f`b
`B100`F9d9 return list.size();`f`b
`B100`F9d9}`f`b

Zur Verdeutlichung, dass hier Wildcards unnötig sind, und es eigentlich gar nicht um irgendeine Varianz geht, sei folgende Implementierung der obigen Funktion angegeben:

`B100`F9d9<T> int readSize(List<T> list) {`f`b
`B100`F9d9 return list.size();`f`b
`B100`F9d9}`f`b

>>Weblinks

• Ina Brenner: Tutorial zu Generics in Java von der Autorin eines Buchs zur Java-Zertifizierung SCJP
• Klaus Kreft, Angelika Langer: Artikelserie zu Generics in Java im JavaSpektrum
• `F33f`_`[Christian Ullenboom`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=Christian_Ullenboom]`_`f: Kapitel zu Generischen Datentypen aus dem Galileo-Openbook `*Java ist auch eine Insel`*

>>Einzelnachweise

`:cite-note-1`!1.`! `F0af`_`[↑`#cite-ref-1]`_`f Nada Amin, Ross Tate: Java and Scala’s Type Systems are Unsound: The Existential Crisis of Null Pointers. In: ACM (Hrsg.): `F33f`_`[OOPSLA`:/page/entry.mu`zim=wikipedia_de_all_nopic_2026-01.zim|entry_path=OOPSLA]`_`f 2016. New York 2016, ISBN 978-1-4503-4444-9, S. 838–848 (englisch, githubusercontent.com [PDF; 215 kB; abgerufen am 31. März 2017]).
`:cite-note-2`!2.`! `F0af`_`[↑`#cite-ref-2]`_`f Joachim Goll, Cornelia Heinisch: Java als erste Programmiersprache: Grundkurs für Hochschulen. 8. Auflage. Springer, Wiesbaden 2016, ISBN 978-3-658-12117-4, S. 725.
`:cite-note-3`!3.`! `F0af`_`[↑`#cite-ref-3]`_`f Reinhard Schiedermeier: Programmieren mit Java. 2. Auflage. Pearson Studium, München 2010, ISBN 978-3-86894-031-2, S. 375.

`c`F0af`_`[↑ Back to top`#top]`_`f`a